home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-09-16 | 7.1 KB | 211 lines | [TEXT/CCL2] |
- ;;-*- Mode: Lisp; Package: CCL -*-
- ;;
- ;; resources.lisp
- ;;
- ;; Simple resource accessors
- ;;
-
- ;;;;;;;;;;;;;;;;
- ;;
- ;; Modification History
- ;;
- ;; 04/28/93 mwp Release
- ;; 04/24/92 bill export get-string & get-ind-string (thanx to Bob Strong)
- ;; ------------- 2.0
- ;; 12/12/91 gb %signal-error -> %err-disp.
- ;; 12/12/91 bill get-resource defaults to loading the resource
- ;; ------------- 2.0b4
- ;; 11/20/91 bill open-resource-file now resolves aliases
- ;; 09/27/91 bill $fnfErr & friends -> #$fnfErr & #friends
- ;; 07/05/91 bill New file
- ;;
-
-
- (in-package :ccl)
-
- (eval-when (:compile-toplevel :load-toplevel :execute)
- (export '(with-open-resource-file open-resource-file close-resource-file
- use-resource-file current-resource-file using-resource-file
- get-resource load-resource release-resource
- add-resource delete-resource remove-resource
- get-string get-ind-string)))
-
-
- ; Execute the BODY with REFNUM-VAR bound to the refnum for the resource
- ; file of FILE. :IF-DOES-NOT-EXIST can be NIL, :ERROR, or :CREATE
- (defmacro with-open-resource-file ((refnum-var file &key (if-does-not-exist :error))
- &body body)
- `(let ((,refnum-var nil))
- (unwind-protect
- (progn
- (setq ,refnum-var
- (open-resource-file ,file :if-does-not-exist ',if-does-not-exist))
- ,@body)
- (if ,refnum-var
- (close-resource-file ,refnum-var)))))
-
- ; Open the resource FILE and return it's refnum.
- ; if-does-not-exist can be :error, nil or :create (just like OPEN).
- ; If ERRORP is NIL and there is an error, return two values: NIL and
- ; the error code.
- (defun open-resource-file (file &key (if-does-not-exist :error) (errorp t))
- (let ((real-file (probe-file file))) ; resolve alias
- (setq real-file (mac-namestring (or real-file file)))
- (with-pstr (pf (mac-namestring real-file))
- (let ((res (#_OpenResFile pf)))
- (declare (fixnum res))
- (when (< res 0)
- (flet ((err (code)
- (if errorp
- (signal-file-error code file)
- (return-from open-resource-file (values nil code)))))
- (declare (dynamic-extent #'err))
- (let ((code (#_ResError)))
- (unless (or (eq code #$fnfErr)
- (eq code #$eofErr)
- (eq code #$resFNotFound))
- (err code))
- (case if-does-not-exist
- (:create
- (#_CreateResFile pf)
- (setq res (#_OpenResFile pf))
- (when (< res 0) (err (#_ResError))))
- (:error
- (err code))
- ((nil) (return-from open-resource-file nil))
- (t (error (%badarg if-does-not-exist '(member nil :create :error))))))))
- res))))
-
- ; Close the resource file with the given refnum
- (defun close-resource-file (refnum)
- (#_CloseResFile refnum)
- (res-error))
-
- ; General error checker for resource manager traps
- (defun res-error ()
- (let ((err (#_ResError)))
- (unless (eql 0 err)
- (%err-disp err))))
-
- ; Use the resource file with the given refnum
- (defun use-resource-file (refnum)
- (prog1
- (#_CurResFile)
- (#_UseResFile refnum)
- (res-error)))
-
- (defmacro using-resource-file (refnum &body body)
- (let ((old-refnum (gensym)))
- `(let (,old-refnum)
- (unwind-protect
- (progn
- (setq ,old-refnum (use-resource-file ,refnum))
- ,@body)
- (when ,old-refnum
- (use-resource-file ,old-refnum))))))
-
- (defun current-resource-file ()
- (#_CurResFile))
-
- ; Get a resource with the given type and name-or-number.
- ; (string type) should be a four-character string
- ; name-or-number should be an integer or a string
- ; if used-file-only? is true, Get1Resource is used instead of GetResource.
- ; if load? is true (the default), load the resource as well.
- ; Return NIL if the resource is not found for any reason.
- (defun get-resource (type name-or-number &optional
- used-file-only?
- (load? t))
- (let ((res (if (integerp name-or-number)
- (if used-file-only?
- (#_Get1Resource type name-or-number)
- (#_GetResource type name-or-number))
- (with-pstr (ps name-or-number)
- (if used-file-only?
- (#_Get1NamedResource type ps)
- (#_GetNamedResource type ps))))))
- (unless (%null-ptr-p res)
- (when load?
- (load-resource res))
- res)))
-
- ; Get the 'STR ' resource with the given NAME-OR-NUMBER
- (defun get-string (name-or-number &optional used-file-only? dont-release)
- (let ((str (get-resource "STR " name-or-number used-file-only?)))
- (when str
- (unwind-protect
- (%get-string str)
- (unless dont-release (#_ReleaseResource str))))))
-
- ; get the INDEX'th string from the 'STR#' resource with the given NAME-OR-NUMBER
- ; Returns NIL if there is no such 'STR#' resource.
- ; Returns two values, NIL and the number of strings in the resource, if there
- ; is a matching 'STR#' resource, but the INDEX is too big.
- ; INDEX starts at 1 to copy the broken Mac definition.
- (defun get-ind-string (name-or-number index &optional used-file-only? dont-release)
- (unless (and (fixnump index) (>= index 1))
- (report-bad-arg index '(fixnum 1 *)))
- (let ((index (1- (the fixnum index)))
- (str# (get-resource "STR#" name-or-number used-file-only? nil)))
- (declare (fixnum index))
- (when str#
- (unwind-protect
- (without-interrupts ; don't want anyone to purge this resource
- (load-resource str#)
- (let ((count (%hget-word str#)))
- (if (<= count index)
- (values nil count)
- (let ((offset 2))
- (dotimes (i index)
- (declare (fixnum i))
- (setq offset (+ 1 offset (%hget-byte str# offset))))
- (%get-string str# offset)))))
- (unless dont-release (#_ReleaseResource str#))))))
-
- ; Load a resource
- (defun load-resource (resource)
- (#_LoadResource resource)
- (res-error))
-
- ; Release the given resource
- (defun release-resource (resource)
- (#_ReleaseResource resource)
- (res-error))
-
- ; Add resource to the currently used resource
- (defun add-resource (resource type id &key name attributes)
- (with-pstr (ps (or name ""))
- (#_AddResource resource type id ps)
- (res-error)
- (when attributes
- (#_SetResAttrs resource attributes)
- (res-error))
- resource))
-
- (defun write-resource (resource)
- (#_WriteResource resource)
- (res-error))
-
- (defun delete-resource (type id-or-name &optional (used-file-only? t))
- (unwind-protect
- (progn
- (#_SetResLoad nil)
- (let ((resource (get-resource type id-or-name used-file-only?)))
- (when resource
- (remove-resource resource)
- (#_DisposHandle resource)
- t)))
- (#_SetResLoad t)))
-
- ; Note that this does not free the memory allocated for the resource.
- (defun remove-resource (resource)
- (using-resource-file (#_HomeResFile resource)
- (#_RmveResource resource))
- (res-error))
-
- (defun detach-resource (resource)
- (#_DetachResource resource)
- (res-error))
-
- (provide "RESOURCES")
-